package com.kl;

import com.kl.constant.KeyParams;
import com.kl.constant.Windows;
import com.kl.model.pojo.Explode;
import com.kl.utils.ContextUtil;
import com.kl.utils.ResourceUtil;
import lombok.Getter;
import lombok.Setter;

import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.Optional;
import java.util.concurrent.*;
import java.util.concurrent.locks.LockSupport;


/**
 *
 *  程序启动入口
 *
 */
public class App extends JFrame implements Runnable
{
    @Getter
    private static final ThreadPoolExecutor POOL = new ThreadPoolExecutor(
            40,50,60, TimeUnit.SECONDS,
            new ArrayBlockingQueue<>(200),
            Executors.defaultThreadFactory(),
            new ThreadPoolExecutor.DiscardOldestPolicy()
    );
    @Getter
    private volatile static CopyOnWriteArrayList<Explode> EXPLODES =new CopyOnWriteArrayList<>();
    @Getter
    private static volatile ConcurrentMap<String,Object> CACHE = new ConcurrentHashMap<>();

    @Getter
    @Setter
    private TankGame tankGame;

    static {
        String a = "enemy";
        String b = "hero";
        String suffix =".png";
        try {
            CACHE.put(KeyParams.ED,ImageIO.read(new File(ResourceUtil.getSrcPath(a+KeyParams.DOWN+suffix))));
            CACHE.put(KeyParams.EL,ImageIO.read(new File(ResourceUtil.getSrcPath(a+KeyParams.LEFT+suffix))));
            CACHE.put(KeyParams.ER,ImageIO.read(new File(ResourceUtil.getSrcPath(a+KeyParams.RIGHT+suffix))));
            CACHE.put(KeyParams.EU,ImageIO.read(new File(ResourceUtil.getSrcPath(a+KeyParams.UP+suffix))));

            CACHE.put(KeyParams.HD,ImageIO.read(new File(ResourceUtil.getSrcPath(b+KeyParams.DOWN+suffix))));
            CACHE.put(KeyParams.HL,ImageIO.read(new File(ResourceUtil.getSrcPath(b+KeyParams.LEFT+suffix))));
            CACHE.put(KeyParams.HR,ImageIO.read(new File(ResourceUtil.getSrcPath(b+KeyParams.RIGHT+suffix))));
            CACHE.put(KeyParams.HU,ImageIO.read(new File(ResourceUtil.getSrcPath(b+KeyParams.UP+suffix))));

            CACHE.put(KeyParams.BEGIN_GAME,ImageIO.read(new File(ResourceUtil.getSrcPath("beginGame.jpg"))));
            CACHE.put(KeyParams.LINK_MODE,ImageIO.read(new File(ResourceUtil.getSrcPath("linkMode.jpg"))));
            CACHE.put(KeyParams.GAME_SETTING,ImageIO.read(new File(ResourceUtil.getSrcPath("setting.jpg"))));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

    }
    public App(){
        JPanel innerPanel = new JPanel();
        innerPanel.setLayout(new BorderLayout());
        Dimension dimension = new Dimension(Windows.WIDTH, Windows.HEIGHT);
        //主面板
        JPanel mainBox = initComponents();
        innerPanel.add(mainBox,BorderLayout.CENTER);
        innerPanel.setBackground(Color.gray);
        this.getContentPane().add(innerPanel);
        this.setSize(dimension);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setLocationRelativeTo(null);
        this.setVisible(true);
    }

    public static void main( String[] args ) throws Exception {
        App app = new App();
        getPOOL().execute(app);
    }

    /**
     * 初始化界面：主面板
     * @return
     */
    private JPanel initComponents() {
        JPanel jPanel = (JPanel) CACHE.get(KeyParams.BEGIN_PANEL);
        if (jPanel!=null){
            return jPanel;
        }
        Dimension commonSize = new Dimension(233, 48);
        JPanel box = new JPanel();
        box.setBackground(Color.gray);
        box.setLayout(new FlowLayout(FlowLayout.CENTER,500,10));
//        box.setLayout(new BoxLayout(box, BoxLayout.Y_AXIS));

        JButton startGame=new JButton(new ImageIcon(((BufferedImage) ContextUtil.getCache(KeyParams.BEGIN_GAME))));
        startGame.setPreferredSize(commonSize);
        startGame.addActionListener(e->{
            //获取内容面板
            JPanel contentPane = (JPanel) this.getContentPane();
            //内部面板
            JPanel innerPane = (JPanel) contentPane.getComponent(0);
            //移除主面板
            innerPane.remove(0);
            this.tankGame = new TankGame(this);
            //新增游戏面板
            innerPane.add(this.tankGame);
            this.setContentPane(contentPane);
            SwingUtilities.updateComponentTreeUI(this);
            TankGame.runGame();
            getPOOL().execute(this.tankGame);
        });
        box.add(startGame);

        JButton linkMode = new JButton(new ImageIcon(((BufferedImage) ContextUtil.getCache(KeyParams.LINK_MODE))));
        linkMode.addActionListener(e->{
            JOptionPane.showMessageDialog(null,"功能开发中》。。。","提示",JOptionPane.INFORMATION_MESSAGE);
        });
        linkMode.setPreferredSize(commonSize);
        box.add(linkMode);

        JButton gameSetting = new JButton(new ImageIcon(((BufferedImage) ContextUtil.getCache(KeyParams.GAME_SETTING))));
        gameSetting.addActionListener(e->{
            JOptionPane.showMessageDialog(null,"功能开发中》。。。","提示",JOptionPane.INFORMATION_MESSAGE);
        });
        gameSetting.setPreferredSize(commonSize);
        box.add(gameSetting);
        JLabel jLabel = new JLabel("开始游戏后,请让当前窗口进入非活跃状态 , 然后再点击程序进入活跃状态 , 否则我方坦克无法行动(此BUG暂时无法解决)");
        JLabel jLabel1 = new JLabel("移动键：W S A D 攻击键：J");
        box.add(jLabel);
        box.add(jLabel1);
        CACHE.put(KeyParams.BEGIN_PANEL,box);
        return box;
    }

    @Override
    public void run() {
        while (true){
            boolean present = Optional.ofNullable(this.tankGame).isPresent();
            if (present && TankGame.isEnd()) {
                try {
                    SwingUtilities.invokeAndWait(()->{
                        //关闭上一个面板
                        try {
                            this.tankGame.close();
                            this.tankGame=null;
                        } catch (IOException e) {
                            throw new RuntimeException(e);
                        }
                        JPanel innerPane = (JPanel) this.getContentPane().getComponent(0);
                        innerPane.remove(0);
                        innerPane.add((JPanel) CACHE.get(KeyParams.BEGIN_PANEL),BorderLayout.CENTER);
                        this.setContentPane(this.getContentPane());
                    });
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                } catch (InvocationTargetException e) {
                    throw new RuntimeException(e);
                }
            }else {
                Object o = CACHE.get(KeyParams.LOCK);
                if (o==null) {
                    CACHE.put(KeyParams.LOCK,Thread.currentThread());
                }else {
                    Thread cur = (Thread) o;
                    if (!cur.isAlive()) {
                        CACHE.put(KeyParams.LOCK,Thread.currentThread());
                    }
                }
                LockSupport.park();
            }
        }
    }
}
